package com.hmy.finance.service.receipt.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.hmy.ccp.error.exception.HMYRuntimeException;
import com.hmy.finance.api.common.enums.receipt.InsufficientExpensesMethodEnum;
import com.hmy.finance.common.constants.CommonConstants;
import com.hmy.finance.dal.mapper.receipt.CustomerAccountTradeMapper;
import com.hmy.finance.dal.mapper.receipt.CustomerBalanceAccountMapper;
import com.hmy.finance.dal.mapper.receipt.CustomerContactorAccountTradeMapper;
import com.hmy.finance.dal.mapper.receipt.CustomerContactorBalanceAccountMapper;
import com.hmy.finance.dal.po.receipt.CustomerAccountTradePo;
import com.hmy.finance.dal.po.receipt.CustomerBalanceAccountPo;
import com.hmy.finance.dal.po.receipt.CustomerContactorAccountTradePo;
import com.hmy.finance.dal.po.receipt.CustomerContactorBalanceAccountPo;
import com.hmy.finance.service.receipt.IncomeExpensesService;
import com.hmy.finance.service.receipt.dto.contactorAccount.ContactorExpensesDto;
import com.hmy.finance.service.receipt.dto.contactorAccount.ContactorIncomeDto;
import com.hmy.finance.service.receipt.dto.contactorAccount.ContactorTradeDto;
import com.hmy.finance.service.receipt.dto.contactorAccount.TransferDto;
import com.hmy.finance.service.receipt.dto.customerAccount.CustomerExpensesDto;
import com.hmy.finance.service.receipt.dto.customerAccount.CustomerIncomeDto;
import com.hmy.finance.service.receipt.dto.customerAccount.CustomerTradeDto;
import com.hmy.finance.service.receipt.rdto.TradeRdto;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class IncomeExpensesServiceImpl implements IncomeExpensesService {
    @Resource
    private CustomerContactorBalanceAccountMapper contactorBalanceAccountMapper;

    @Resource
    private RedissonClient redissonClient;

    @Resource
    private CustomerContactorAccountTradeMapper contactorAccountTradeMapper;

    @Resource
    private CustomerAccountTradeMapper customerAccountTradeMapper;

    @Resource
    private CustomerBalanceAccountMapper customerBalanceAccountMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TradeRdto incomeBalance(ContactorIncomeDto contactorIncomeDto) {
        log.debug("[联系人账户]-[入账:{}]-[联系人ID:{}]-[入账金额:{}]--[入账时间:{}]", contactorIncomeDto.getBusinessBillId(), contactorIncomeDto.getCustomerContactorId(), contactorIncomeDto.getAmount(), contactorIncomeDto.getFeeIncurredTime());
        CustomerContactorBalanceAccountPo customerContactorBalanceAccountPo = contactorBalanceAccountMapper.selectById(contactorIncomeDto.getCustomerContactorId());
        if (Objects.isNull(customerContactorBalanceAccountPo)) {
            throw new HMYRuntimeException(506500001);
        }
        //Check contactorIncomeDto#amount is greater than zero
        if (contactorIncomeDto.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            log.error("[联系人账户]-[入账:{}]-[联系人ID:{}]-[入账金额小于等于0]", contactorIncomeDto.getBusinessBillId(), contactorIncomeDto.getCustomerContactorId());
            throw new HMYRuntimeException(506500010);
        }
        synchronized (customerContactorBalanceAccountPo) {
            //获取分布式锁
            RLock lock = redissonClient.getLock(CommonConstants.CONTACTOR_BALANCE_ACCOUNT_LOCK_PREFIX + customerContactorBalanceAccountPo.getCustomerId());
            try {
                if (!lock.tryLock(2, 5, TimeUnit.SECONDS)) {
                    throw new HMYRuntimeException(506500005);
                }
            } catch (InterruptedException e) {
                log.error("[联系人账户]-[入账:{}]-[联系人ID:{}]-[获取分布式锁失败]", contactorIncomeDto.getBusinessBillId(), customerContactorBalanceAccountPo.getCustomerId());
                throw new HMYRuntimeException(506500005);
            }
            try {
                log.debug("[联系人账户]-[入账:{}]-[联系人ID:{}]-[变更前余额:{}]", contactorIncomeDto.getBusinessBillId(), customerContactorBalanceAccountPo.getCustomerId(), customerContactorBalanceAccountPo.getBalanceAmount());
                contactorIncomeDto.setBalanceAccount(customerContactorBalanceAccountPo);
                //构建更新条件
                LambdaUpdateWrapper<CustomerContactorBalanceAccountPo> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(CustomerContactorBalanceAccountPo::getContactorId, customerContactorBalanceAccountPo.getContactorId());
                updateWrapper.eq(CustomerContactorBalanceAccountPo::getBalanceAmount, customerContactorBalanceAccountPo.getBalanceAmount());
                //更新余额

                customerContactorBalanceAccountPo.setBalanceAmount(customerContactorBalanceAccountPo.getBalanceAmount().add(contactorIncomeDto.getAmount()));
                customerContactorBalanceAccountPo.setTotalIncomeAmount(customerContactorBalanceAccountPo.getTotalIncomeAmount().add(contactorIncomeDto.getAmount()));
                CustomerContactorAccountTradePo accountTrade = getContractorAccountTrade(ContactorTradeDto.buildFromIncomeDto(contactorIncomeDto));
                if (contactorAccountTradeMapper.insert(accountTrade) < 1) {
                    log.error("[联系人账户]-[入账:{}]-[联系人ID:{}]-[入账失败]", contactorIncomeDto.getBusinessBillId(), customerContactorBalanceAccountPo.getCustomerId());
                    throw new HMYRuntimeException(506500002);
                }
                if (contactorBalanceAccountMapper.update(customerContactorBalanceAccountPo, updateWrapper) < 1) {
                    log.error("[联系人账户]-[入账:{}]-[联系人ID:{}]-[入账失败]", contactorIncomeDto.getBusinessBillId(), customerContactorBalanceAccountPo.getCustomerId());
                    throw new HMYRuntimeException(506500003);
                }
                log.debug("[联系人账户]-[入账:{}]-[联系人ID:{}]-[入账成功]-[入账后余额:{}]", contactorIncomeDto.getBusinessBillId(), customerContactorBalanceAccountPo.getCustomerId(), customerContactorBalanceAccountPo.getBalanceAmount());
                return new TradeRdto(accountTrade.getCustomerContactorId(), accountTrade.getAmount(), accountTrade.getId());
            } catch (Exception e) {
                log.error("[联系人账户]-[入账:{}]-[联系人ID:{}]-[入账异常]", contactorIncomeDto.getBusinessBillId(), customerContactorBalanceAccountPo.getCustomerId());
                throw new HMYRuntimeException(506500005);
            } finally {
                lock.unlock();
            }
        }
    }

    private CustomerContactorAccountTradePo getContractorAccountTrade(ContactorTradeDto contactorTradeDto) {
        CustomerContactorAccountTradePo accountTrade = new CustomerContactorAccountTradePo();
        accountTrade.setCustomerContactorId(contactorTradeDto.getBalanceAccount().getContactorId());
        accountTrade.setCustomerId(contactorTradeDto.getBalanceAccount().getCustomerId());
        accountTrade.setBusinessId(contactorTradeDto.getBusinessBillId());
        accountTrade.setAmount(contactorTradeDto.getAmount());
        accountTrade.setBusinessType(contactorTradeDto.getBusinessType());
        accountTrade.setFeeIncurredTime(contactorTradeDto.getFeeIncurredTime());
        accountTrade.setTradeType(contactorTradeDto.getTradeType());
//        if (UserContextUtil.getCurrentUser() != null) {
//            accountTrade.setCreatorId(UserContextUtil.getCurrentUser().getId());
//            accountTrade.setUpdaterId(UserContextUtil.getCurrentUser().getId());
//            accountTrade.setCreatorName(UserContextUtil.getCurrentUser().getUserName());
//            accountTrade.setUpdaterName(UserContextUtil.getCurrentUser().getUserName());
//        } else {
        accountTrade.setCreatorId(-1L);
        accountTrade.setUpdaterId(-1L);
        accountTrade.setCreatorName("System");
        accountTrade.setUpdaterName("System");
//        }
        return accountTrade;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TradeRdto expensesBalance(ContactorExpensesDto contactorExpensesDto) {
        log.info("[联系人账户]-[支出:{}]-[联系人ID:{}]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getContactorId());
        CustomerContactorBalanceAccountPo customerContactorBalanceAccountPo = contactorBalanceAccountMapper.selectById(contactorExpensesDto.getContactorId());
        if (customerContactorBalanceAccountPo == null) {
            log.error("[联系人账户]-[支出:{}]-[联系人ID:{}]-[联系人账户不存在]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getContactorId());
            throw new HMYRuntimeException(506500001);
        }
        //Check contactorExpensesDto#amount is greater than zero
        if (contactorExpensesDto.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            log.error("[联系人账户]-[支出:{}]-[联系人ID:{}]-[支出金额小于等于0]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getContactorId());
            throw new HMYRuntimeException(506500009);
        }
        //构建更新条件
        synchronized (customerContactorBalanceAccountPo) {
            RLock lock = redissonClient.getLock(CommonConstants.CONTACTOR_BALANCE_ACCOUNT_LOCK_PREFIX + customerContactorBalanceAccountPo.getCustomerId());
            try {
                if (!lock.tryLock(2, 5, TimeUnit.SECONDS)) {
                    log.error("[联系人账户]-[支出:{}]-[联系人ID:{}]-[锁定失败]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getContactorId());
                    throw new HMYRuntimeException(506500005);
                }
            } catch (Exception e) {
                log.error("[联系人账户]-[支出:{}]-[联系人ID:{}]-[锁定异常]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getContactorId());
                throw new HMYRuntimeException(506500005);
            }
            try {
                contactorExpensesDto.setBalanceAccount(customerContactorBalanceAccountPo);
                if (customerContactorBalanceAccountPo.getBalanceAmount().compareTo(contactorExpensesDto.getAmount()) < 0) {
                    //联系人账户余额不足，需要从对应客户账户进行划拨
                    log.error("[联系人账户]-[支出:{}]-[联系人ID:{}]-[联系人账户余额不足:{}]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getBalanceAccount().getContactorId(), customerContactorBalanceAccountPo.getBalanceAmount());
                    TransferDto transferDto = new TransferDto();
                    transferDto.setAmount(contactorExpensesDto.getAmount().subtract(contactorExpensesDto.getBalanceAccount().getBalanceAmount()));
                    transferDto.setBusinessBillId(contactorExpensesDto.getBusinessBillId());
                    transferDto.setBusinessType(contactorExpensesDto.getBusinessType());
                    transferDto.setFeeIncurredTime(contactorExpensesDto.getFeeIncurredTime());
                    transferDto.setContactorId(contactorExpensesDto.getBalanceAccount().getContactorId());
                    transferDto.setCustomerId(contactorExpensesDto.getBalanceAccount().getCustomerId());
                    Boolean transferResult = this.transferBalance(transferDto);
                    if (Objects.nonNull(transferResult)) {
                        customerContactorBalanceAccountPo = contactorBalanceAccountMapper.selectById(contactorExpensesDto.getContactorId());
                        contactorExpensesDto.setBalanceAccount(customerContactorBalanceAccountPo);
                        log.debug("[联系人账户]-[支出:{}]-[联系人ID:{}]-[划拨成功:{}]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getBalanceAccount().getContactorId(), customerContactorBalanceAccountPo.getBalanceAmount());
                        if (customerContactorBalanceAccountPo.getBalanceAmount().compareTo(contactorExpensesDto.getAmount()) < 0) {
                            log.error("[联系人账户]-[支出:{}]-[联系人ID:{}]-[划拨后余额仍旧不足]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getBalanceAccount().getContactorId());
                            if (contactorExpensesDto.getInsufficientExpensesMethod().equals(InsufficientExpensesMethodEnum.REFUSE)) {
                                throw new HMYRuntimeException(506500006);
                            }
                            contactorExpensesDto.setAmount(customerContactorBalanceAccountPo.getBalanceAmount());
                        }
                    } else {
                        log.error("[联系人账户]-[支出:{}]-[联系人ID:{}]-[划拨失败]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getBalanceAccount().getContactorId());
                        throw new HMYRuntimeException(506500006);
                    }
                }
                log.debug("[联系人账户]-[支出:{}]-[联系人ID:{}]-[联系人账户支出前余额:{}]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getBalanceAccount().getContactorId(), customerContactorBalanceAccountPo.getBalanceAmount());
                //组装更新条件
                LambdaUpdateWrapper<CustomerContactorBalanceAccountPo> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(CustomerContactorBalanceAccountPo::getContactorId, contactorExpensesDto.getBalanceAccount().getContactorId());
                updateWrapper.eq(CustomerContactorBalanceAccountPo::getBalanceAmount, contactorExpensesDto.getBalanceAccount().getBalanceAmount());
                customerContactorBalanceAccountPo.setBalanceAmount(customerContactorBalanceAccountPo.getBalanceAmount().subtract(contactorExpensesDto.getAmount()));
                customerContactorBalanceAccountPo.setTotalExpensesAmount(customerContactorBalanceAccountPo.getTotalExpensesAmount().add(contactorExpensesDto.getAmount()));
                log.debug("[[联系人账户]-[支出:{}]-[联系人ID:{}]-[联系人账户支出后余额:{}]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getBalanceAccount().getContactorId(), customerContactorBalanceAccountPo.getBalanceAmount());
                CustomerContactorAccountTradePo customerContactorAccountTradePo = getContractorAccountTrade(ContactorTradeDto.buildFromExpensesDto(contactorExpensesDto));
                if (contactorAccountTradeMapper.insert(customerContactorAccountTradePo) < 1) {
                    log.error("[联系人账户]-[支出:{}]-[联系人ID:{}]-[联系人账户支出异常]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getBalanceAccount().getContactorId());
                    throw new HMYRuntimeException(506500005);
                }
                if (contactorBalanceAccountMapper.update(customerContactorBalanceAccountPo, updateWrapper) < 0) {
                    log.error("[联系人账户]-[支出:{}]-[联系人ID:{}]-[联系人账户更新失败]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getBalanceAccount().getContactorId());
                    throw new HMYRuntimeException(506500005);
                }
                log.debug("[联系人账户]-[支出:{}]-[联系人ID:{}]-[联系人账户支出成功]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getBalanceAccount().getContactorId());
                return new TradeRdto(customerContactorBalanceAccountPo.getContactorId(), customerContactorAccountTradePo.getAmount(), customerContactorAccountTradePo.getId());
            } catch (Exception e) {
                log.error("[联系人账户]-[支出:{}]-[联系人ID:{}]-[联系人账户支出异常]", contactorExpensesDto.getBusinessBillId(), contactorExpensesDto.getBalanceAccount().getContactorId(), e);
                throw new HMYRuntimeException(506500005);
            } finally {
                lock.unlock();
            }
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean transferBalance(TransferDto transferDto) {
        TradeRdto customerExpensesTradeRdto = this.expensesBalance(transferDto.getCustomerExpensesDto());
        if (Objects.nonNull(customerExpensesTradeRdto) && customerExpensesTradeRdto.getResult()) {
            log.debug("[联系人账户]-[支出:{}]-[联系人ID:{}]-[客户账户支出成功]", transferDto.getBusinessBillId(), transferDto.getCustomerId());
            TradeRdto contactorIncomeRdto = this.incomeBalance(transferDto.getContactorIncomeDto(customerExpensesTradeRdto.getTradeId()));
            if (Objects.nonNull(contactorIncomeRdto)) {
                log.debug("[联系人账户]-[支出:{}]-[联系人ID:{}]-[联系人账户入账成功]", transferDto.getBusinessBillId(), transferDto.getContactorId());
                return contactorIncomeRdto.getResult();
            }
        }
        throw new HMYRuntimeException(506500007);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TradeRdto incomeBalance(CustomerIncomeDto customerIncomeDto) {
        log.info("[客户账户]-[入账:{}]-[客户ID:{}]-[入账金额:{}]--[入账时间:{}]", customerIncomeDto.getBusinessBillId(), customerIncomeDto.getCustomerId(), customerIncomeDto.getAmount(), customerIncomeDto.getFeeIncurredTime());
        CustomerBalanceAccountPo customerBalanceAccountPo = customerBalanceAccountMapper.selectById(customerIncomeDto.getCustomerId());
        if (Objects.isNull(customerBalanceAccountPo)) {
            log.error("[客户账户]-[入账:{}]-[客户ID:{}]-[客户账户不存在]", customerIncomeDto.getBusinessBillId(), customerIncomeDto.getCustomerId());
            throw new HMYRuntimeException(506400001);
        }
        //Check customerIncomeDto#amount is greater than zero
        if (customerIncomeDto.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            log.error("[客户账户]-[入账:{}]-[客户ID:{}]-[入账金额小于等于0]", customerIncomeDto.getBusinessBillId(), customerIncomeDto.getCustomerId());
            throw new HMYRuntimeException(506400010);
        }
        synchronized (customerBalanceAccountPo) {
            //获取分布式锁
            RLock lock = redissonClient.getLock(CommonConstants.CUSTOMER_BALANCE_ACCOUNT_LOCK_PREFIX + customerBalanceAccountPo.getCustomerId());
            try {
                if (!lock.tryLock(10, TimeUnit.SECONDS)) {
                    throw new HMYRuntimeException(506400005);
                }
            } catch (InterruptedException e) {
                log.error("[客户账户]-[入账:{}]-[客户ID:{}]-[获取分布式锁失败]", customerIncomeDto.getBusinessBillId(), customerBalanceAccountPo.getCustomerId());
                throw new HMYRuntimeException(506400005);
            }
            try {
                log.info("[客户账户]-[入账:{}]-[客户ID:{}]-[变更前余额:{}]", customerIncomeDto.getBusinessBillId(), customerBalanceAccountPo.getCustomerId(), customerBalanceAccountPo.getBalanceAmount());
                customerIncomeDto.setCustomerBalanceAccountPo(customerBalanceAccountPo);
                //构建更新条件
                LambdaQueryWrapper<CustomerBalanceAccountPo> updateWrapper = new LambdaQueryWrapper<>();
                updateWrapper.eq(CustomerBalanceAccountPo::getCustomerId, customerBalanceAccountPo.getCustomerId());
                updateWrapper.eq(CustomerBalanceAccountPo::getBalanceAmount, customerBalanceAccountPo.getBalanceAmount());
                //设置入账后账户余额
                customerBalanceAccountPo.setBalanceAmount(customerBalanceAccountPo.getBalanceAmount().add(customerIncomeDto.getAmount()));
                customerBalanceAccountPo.setTotalIncomeAmount(customerBalanceAccountPo.getTotalIncomeAmount().add(customerIncomeDto.getAmount()));
                CustomerAccountTradePo customerAccountTradePo = getCustomerAccountTradePo(CustomerTradeDto.buildFromIncomeDto(customerIncomeDto));
                if (customerAccountTradeMapper.insert(customerAccountTradePo) < 1) {
                    log.error("[客户账户]-[入账:{}]-[客户ID:{}]-[插入交易流水失败]", customerIncomeDto.getBusinessBillId(), customerBalanceAccountPo.getCustomerId());
                    throw new HMYRuntimeException(506400002);
                }
                if (customerBalanceAccountMapper.update(customerBalanceAccountPo, updateWrapper) < 1) {
                    log.error("[客户账户]-[入账:{}]-[客户ID:{}]-[更新余额失败]", customerIncomeDto.getBusinessBillId(), customerBalanceAccountPo.getCustomerId());
                    throw new HMYRuntimeException(506400003);
                }
                log.info("[客户账户]-[入账:{}]-[客户ID:{}]-[变更后余额:{}]", customerIncomeDto.getBusinessBillId(), customerBalanceAccountPo.getCustomerId(), customerBalanceAccountPo.getBalanceAmount());
                return new TradeRdto(customerBalanceAccountPo.getCustomerId(), customerAccountTradePo.getAmount(), customerAccountTradePo.getId());
            } finally {
                lock.unlock();
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TradeRdto expensesBalance(CustomerExpensesDto customerExpensesDto) {
        log.info("[客户账户]-[支出:{}]-[客户ID:{}]-[支出金额:{}]--[支出时间:{}]", customerExpensesDto.getBusinessBillId(), customerExpensesDto.getCustomerId(), customerExpensesDto.getAmount(), customerExpensesDto.getFeeIncurredTime());
        CustomerBalanceAccountPo customerBalanceAccountPo = customerBalanceAccountMapper.selectById(customerExpensesDto.getCustomerId());
        if (Objects.isNull(customerBalanceAccountPo)) {
            log.error("[客户账户]-[支出:{}]-[客户ID:{}]-[客户账户不存在]", customerExpensesDto.getBusinessBillId(), customerExpensesDto.getCustomerId());
            throw new HMYRuntimeException(506400001);
        }
        //Check customerExpensesDto#amount is greater than zero
        if (customerExpensesDto.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            log.error("[客户账户]-[支出:{}]-[客户ID:{}]-[支出金额小于等于0]", customerExpensesDto.getBusinessBillId(), customerExpensesDto.getCustomerId());
            throw new HMYRuntimeException(506400009);
        }
        synchronized (customerBalanceAccountPo) {
            //获取分布式锁
            RLock lock = redissonClient.getLock(CommonConstants.CUSTOMER_BALANCE_ACCOUNT_LOCK_PREFIX + customerBalanceAccountPo.getCustomerId());
            try {
                if (!lock.tryLock(10, TimeUnit.SECONDS)) {
                    throw new HMYRuntimeException(506400005);
                }
            } catch (InterruptedException e) {
                log.error("[客户账户]-[入账:{}]-[客户ID:{}]-[获取分布式锁失败]", customerExpensesDto.getBusinessBillId(), customerBalanceAccountPo.getCustomerId());
                throw new HMYRuntimeException(506400005);
            }
            try {
                log.info("[客户账户]-[支出:{}]-[客户ID:{}]-[变更前余额:{}]", customerExpensesDto.getBusinessBillId(), customerBalanceAccountPo.getCustomerId(), customerBalanceAccountPo.getBalanceAmount());
                customerExpensesDto.setCustomerBalanceAccountPo(customerBalanceAccountPo);
                if (customerBalanceAccountPo.getBalanceAmount().compareTo(BigDecimal.ZERO) <= 0) {
                    throw new HMYRuntimeException(506400004);
                }
                if (customerBalanceAccountPo.getBalanceAmount().compareTo(customerExpensesDto.getAmount()) < 0) {
                    log.error("[客户账户]-[支出:{}]-[客户ID:{}]-[余额不足]", customerExpensesDto.getBusinessBillId(), customerBalanceAccountPo.getCustomerId());
                    if (customerExpensesDto.getInsufficientExpensesMethod().equals(InsufficientExpensesMethodEnum.REFUSE)) {
                        throw new HMYRuntimeException(506400004);
                    } else {
                        log.info("[客户账户]-[支出:{}]-[客户ID:{}]-[余额不足，支出可支出金额]", customerExpensesDto.getBusinessBillId(), customerBalanceAccountPo.getCustomerId());
                        customerExpensesDto.setAmount(customerBalanceAccountPo.getBalanceAmount());
                    }
                }
                //构建更新条件
                LambdaQueryWrapper<CustomerBalanceAccountPo> updateWrapper = new LambdaQueryWrapper<>();
                updateWrapper.eq(CustomerBalanceAccountPo::getCustomerId, customerBalanceAccountPo.getCustomerId());
                updateWrapper.eq(CustomerBalanceAccountPo::getBalanceAmount, customerBalanceAccountPo.getBalanceAmount());
                //设置支出后账户余额
                customerBalanceAccountPo.setBalanceAmount(customerBalanceAccountPo.getBalanceAmount().subtract(customerExpensesDto.getAmount()));
                customerBalanceAccountPo.setTotalExpensesAmount(customerBalanceAccountPo.getTotalExpensesAmount().add(customerExpensesDto.getAmount()));
                CustomerAccountTradePo customerAccountTradePo = getCustomerAccountTradePo(CustomerTradeDto.buildFromExpensesDto(customerExpensesDto));
                if (customerAccountTradeMapper.insert(customerAccountTradePo) < 1) {
                    log.error("[客户账户]-[支出:{}]-[客户ID:{}]-[插入交易流水失败]", customerExpensesDto.getBusinessBillId(), customerBalanceAccountPo.getCustomerId());
                    throw new HMYRuntimeException(506400002);
                }
                if (customerBalanceAccountMapper.update(customerBalanceAccountPo, updateWrapper) < 1) {
                    log.error("[客户账户]-[支出:{}]-[客户ID:{}]-[更新余额失败]", customerExpensesDto.getBusinessBillId(), customerBalanceAccountPo.getCustomerId());
                    throw new HMYRuntimeException(506400003);
                }
                log.info("[客户账户]-[支出:{}]-[客户ID:{}]-[变更后余额:{}]", customerExpensesDto.getBusinessBillId(), customerBalanceAccountPo.getCustomerId(), customerBalanceAccountPo.getBalanceAmount());
                return new TradeRdto(customerAccountTradePo.getCustomerId(), customerAccountTradePo.getAmount(), customerAccountTradePo.getId());
            } finally {
                lock.unlock();
            }
        }
    }

    private static CustomerAccountTradePo getCustomerAccountTradePo(CustomerTradeDto generateDto) {
        //构建账户流水数据
        CustomerAccountTradePo customerAccountTradePo = new CustomerAccountTradePo();
        customerAccountTradePo.setAmount(generateDto.getAmount());
        customerAccountTradePo.setBusinessId(generateDto.getBusinessBillId());
        customerAccountTradePo.setBusinessType(generateDto.getBusinessType());
        customerAccountTradePo.setCustomerId(generateDto.getCustomerBalanceAccount().getCustomerId());
        customerAccountTradePo.setTradeType(generateDto.getTradeType());
        customerAccountTradePo.setFeeIncurredTime(generateDto.getFeeIncurredTime());
        //区分系统任务和手动核销
//        if (UserContextUtil.getCurrentUser() != null) {
//            customerAccountTradePo.setCreatorId(UserContextUtil.getCurrentUser().getId());
//            customerAccountTradePo.setUpdaterId(UserContextUtil.getCurrentUser().getId());
//            customerAccountTradePo.setCreatorName(UserContextUtil.getCurrentUser().getUserName());
//            customerAccountTradePo.setUpdaterName(UserContextUtil.getCurrentUser().getUserName());
//        } else {
        customerAccountTradePo.setCreatorId(-1L);
        customerAccountTradePo.setUpdaterId(-1L);
        customerAccountTradePo.setCreatorName("system");
        customerAccountTradePo.setUpdaterName("system");
//        }
        return customerAccountTradePo;
    }
}
